package com.qianfeng.smartdevices.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qianfeng.smartdevices.cache.AreasCache;
import com.qianfeng.smartdevices.cache.CategoriesCache;
import com.qianfeng.smartdevices.cache.DeviceCache;
import com.qianfeng.smartdevices.dto.ResultCode;
import com.qianfeng.smartdevices.event.ColorCommandEvent;
import com.qianfeng.smartdevices.event.DeviceChangeEvent;
import com.qianfeng.smartdevices.event.PowerCommandEvent;
import com.qianfeng.smartdevices.event.UpdateDeviceStatusEvent;
import com.qianfeng.smartdevices.exceptions.AddErrorException;
import com.qianfeng.smartdevices.exceptions.DeleteErrorException;
import com.qianfeng.smartdevices.exceptions.UpdateErrorException;
import com.qianfeng.smartdevices.mapper.DeviceMapper;
import com.qianfeng.smartdevices.pojo.CheckStatus;
import com.qianfeng.smartdevices.pojo.Device;
import com.qianfeng.smartdevices.service.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class DeviceServiceImpl implements DeviceService {

    private DeviceMapper deviceMapper;
    private CategoriesCache categoriesCache;
    private DeviceCache deviceCache;

    private AreasCache areasCache;

    private ApplicationContext context;
    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    @Autowired
    public void setAreasCache(AreasCache areasCache) {
        this.areasCache = areasCache;
    }

    @Autowired
    public void setDeviceCache(DeviceCache deviceCache) {
        this.deviceCache = deviceCache;
    }

    @Autowired
    public void setCategoriesCache(CategoriesCache categoriesCache) {
        this.categoriesCache = categoriesCache;
    }

    @Autowired
    public void setDeviceMapper(DeviceMapper deviceMapper) {
        this.deviceMapper = deviceMapper;
    }

    @Override
    public PageInfo<Device> findAllDevice(int page,int limit,String address, String status,Long categoryid,Long areaid) {
        PageHelper.startPage(page,limit);
//        List<Device> allDevice = deviceMapper.findAllDevice(address, status,categoryid,areaid);
//        allDevice.forEach(device -> {
//            device.setCategory(categoriesCache.get(device.getCategoryid()));//遍历集合通过key找值，将缓存中的数据遍历到集合中
//
//            device.setAreaname(areasCache.get(device.getAreaid()).getAreaname());
//        });
//        return new PageInfo<>(allDevice);
        List<Device> deviceList = deviceCache.getAllData();
        deviceList.forEach(device -> {
            device.setCategory(categoriesCache.get(device.getCategoryid()));//遍历集合通过key找值，将缓存中的数据遍历到集合中

            device.setAreaname(areasCache.get(device.getAreaid()).getAreaname());
        });
        List<Device> list = deviceList.stream().filter(device -> {
            boolean b1 = ObjectUtils.isEmpty(address) ? true : device.getAddress().contains(address);
            boolean b2 = (ObjectUtils.isEmpty(status) || status.equals("-100")) ? true : device.getStatus().contains(status);
            boolean b3 = (ObjectUtils.isEmpty(categoryid) || categoryid == -100) ? true : device.getCategoryid().equals(categoryid);
            boolean b4 = (ObjectUtils.isEmpty(areaid) || areaid == -100) ? true : device.getAreaid().equals(areaid);
            return b1 && b2 && b3 && b4;
        }).collect(Collectors.toList());
        List<Device> collect = list.stream().skip((page - 1) * limit).limit(limit).collect(Collectors.toList());

        PageInfo<Device> pageInfo = new PageInfo<>(collect);
        pageInfo.setTotal(list.size());
        return  pageInfo;
    }

    @Override
    public void addDevice(Device device) throws Exception{
        if (device==null||device.isNull(CheckStatus.ADD)) {
            throw new AddErrorException("添加的数据不能为空", ResultCode.DATA_NOT_ALLOW_NUL);
        }
        deviceMapper.addDevice(device);
        context.publishEvent(new DeviceChangeEvent());
    }

    @Override
    public void updateDevice(Device device) throws Exception {
        if (device==null||device.isNull(CheckStatus.UPDATE)) {
            throw new UpdateErrorException("更新的数据不能为空", ResultCode.DATA_NOT_ALLOW_NUL);
        }
        deviceMapper.updateDevice(device);
        context.publishEvent(new DeviceChangeEvent());
    }

    @Override
    public void deleteDeviceById(String[] ids) {
        if (ids == null || ids.length == 0) {
            throw new DeleteErrorException("删除需要传递ids",ResultCode.DATA_NOT_ALLOW_NUL);
        }
        deviceMapper.deleteDeviceById(Arrays.asList(ids));
        context.publishEvent(new DeviceChangeEvent());
    }

    @Override
    public void sendCommand(String uuid, String command) {
        String value = null;

        switch (command) {
            case "open":
                value = "0";
                break;
            case "close":
                value = "1";
                break;
            case "change":
                value = "2";
                context.publishEvent(new ColorCommandEvent(uuid, value));
                return;
        }
        System.err.println(Thread.currentThread().getName());
        context.publishEvent(new PowerCommandEvent(uuid,value));
    }

    @Override
    public void updateStatus(String uuid, String status) {
        deviceMapper.updateOffLine(uuid,status);
    }

    @Override
    @EventListener
    @Async
    public void onEvent(UpdateDeviceStatusEvent event) {
        updateStatus(event.getUuid(), event.getStatus());
    }


}
